home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume2 / window / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  49.5 KB

  1. From: Tom Truscott <decvax!mcnc!rti-sel!trt>
  2. Subject: wm - a window manager (part 2 of 4)
  3. Newsgroups: mod.sources
  4. Approved: john@genrad.UUCP
  5.  
  6. Mod.sources:  Volume 2, Issue 32
  7. Submitted by: Tom Truscott <decvax!mcnc!rti-sel!trt>
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    Makefile
  16. #    wm.h
  17. #    cmd.c
  18. #    curses.c
  19. #    getch.c
  20. #    hacks.c
  21. #    help.c
  22. # This archive created: Fri Aug  2 13:13:15 1985
  23. export PATH; PATH=/bin:$PATH
  24. echo shar: extracting "'Makefile'" '(2215 characters)'
  25. if test -f 'Makefile'
  26. then
  27.     echo shar: will not over-write existing file "'Makefile'"
  28. else
  29. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  30. #
  31. #    Makefile for wm
  32. #
  33.  
  34. # Flags for the C compiler.
  35. CFLAGS    = -O
  36.  
  37. # Flags for loader.  You probably do not need any.
  38. LDFLAGS    = 
  39.  
  40. # Final resting place of wm executable.
  41. BIN    = /usr/local
  42.  
  43. # Name of owner and group that you want installed wm to have.
  44. OWNER    = bin
  45. GROUP    = bin
  46.  
  47. # Version of libcurses wm is linked with. This *must* be
  48. # the version that is distributed with wm, since it contains
  49. # several bug fixes necessary to the correct operation of wm.
  50. LIBS    = -lcurses -ltermcap
  51.  
  52. OBJS = cmd.o curses.o getch.o hacks.o help.o misc.o \
  53.     save.o shell.o vterm.o wlist.o wm.o
  54. XSRCS = cmd.c curses.c getch.c hacks.c help.c misc.c \
  55.     save.c shell.c vterm.c wlist.c wm.c
  56.  
  57. wm: $(OBJS)
  58.     $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o wm
  59.  
  60. $(OBJS): wm.h
  61.  
  62. lint: 
  63.     lint -hbux $(SRCS)
  64.  
  65. clean:
  66.     /bin/rm -f *.o wm core *.out
  67.  
  68. install: wm
  69.     install -o $(OWNER) -g $(GROUP) -s wm $(DESTDIR)/$(BIN)
  70.  
  71. depend:
  72.     cat </dev/null >x.c
  73.     for i in ${SRCS}; do \
  74.         (echo `basename $$i .c`.o: $$i >>makedep; \
  75.         /bin/grep '^#[     ]*include' x.c $$i | sed \
  76.             -e 's,<\(.*\)>,"/usr/include/\1",' \
  77.             -e 's/:[^"]*"\([^"]*\)".*/: \1/' \
  78.             -e 's/\.c/.o/' >>makedep); done
  79.     echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
  80.     echo '$$r makedep' >>eddep
  81.     echo 'w' >>eddep
  82.     cp Makefile Makefile.bak
  83.     ed - Makefile < eddep
  84.     rm eddep makedep x.c
  85.     echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
  86.     echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
  87.     echo '# see make depend above' >> Makefile
  88.  
  89. # DO NOT DELETE THIS LINE -- make depend uses it
  90.  
  91. cmd.o: cmd.c
  92. cmd.o: wm.h
  93. curses.o: curses.c
  94. curses.o: wm.h
  95. getch.o: getch.c
  96. getch.o: wm.h
  97. getch.o: /usr/include/signal.h
  98. getch.o: /usr/include/setjmp.h
  99. getch.o: /usr/include/sys/time.h
  100. hacks.o: hacks.c
  101. hacks.o: wm.h
  102. help.o: help.c
  103. help.o: wm.h
  104. misc.o: misc.c
  105. misc.o: wm.h
  106. save.o: save.c
  107. save.o: wm.h
  108. shell.o: shell.c
  109. shell.o: wm.h
  110. shell.o: /usr/include/signal.h
  111. shell.o: /usr/include/errno.h
  112. vterm.o: vterm.c
  113. vterm.o: wm.h
  114. wlist.o: wlist.c
  115. wlist.o: wm.h
  116. wm.o: wm.c
  117. wm.o: wm.h
  118. wm.o: /usr/include/signal.h
  119. wm.o: /usr/include/sys/wait.h
  120. wm.o: /usr/include/sys/time.h
  121. wm.o: /usr/include/sys/resource.h
  122. # DEPENDENCIES MUST END AT END OF FILE
  123. # IF YOU PUT STUFF HERE IT WILL GO AWAY
  124. # see make depend above
  125. SHAR_EOF
  126. if test 2215 -ne "`wc -c < 'Makefile'`"
  127. then
  128.     echo shar: error transmitting "'Makefile'" '(should have been 2215 characters)'
  129. fi
  130. fi # end of overwriting check
  131. echo shar: extracting "'wm.h'" '(6227 characters)'
  132. if test -f 'wm.h'
  133. then
  134.     echo shar: will not over-write existing file "'wm.h'"
  135. else
  136. sed 's/^X//' << \SHAR_EOF > 'wm.h'
  137. /*
  138.  *************
  139.  * DISTRIBUTION NOTICE  July 30 1985
  140.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  141.  *        Research Triangle Institute, (919) 541-7005.
  142.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  143.  *        Naval Research Laboratory, (202) 767-3365.
  144.  * No claims or warranties of any sort are made for this distribution.
  145.  * General permission is granted to copy, but not for profit,
  146.  * any of this distribution, provided that this notice
  147.  * is always included in the copies.
  148.  *************
  149.  */
  150. /*
  151.  * definitions for wm
  152.  */
  153.  
  154. #include "curses.h"
  155. #include <sys/types.h>
  156. #include <ctype.h>
  157.  
  158. #define    CURSEASSIST        /* give curses a hand, sigh. */
  159. #define    SET_WINDOW        /* assist all-wonderful scrolling rectangles */
  160. #define    GAGMEKEYPAD        /* gross hack for arrow keys */
  161. /*#define    SNEAKYTERMCAP        /* /tmp termcap kludge */
  162.  
  163. /* define TERMINFO if we are using a terminfo version of curses */
  164. #ifdef A_STANDOUT
  165. #define    TERMINFO
  166. #endif
  167.  
  168. #ifdef TERMINFO
  169. /* define FASTTERMINFO if your terminfo has a clever doupdate */
  170. /*#define    FASTTERMINFO    /**/
  171. /* define BUGGYTERMINFO if your terminfo has 'certain bugs' */
  172. #define    BUGGYTERMINFO    /**/
  173. #endif
  174.  
  175. /*
  176.  * Definitions for curses
  177.  */
  178. #define    wcury(w)    ((w)->_cury)    /* current (y,x) in window w */
  179. #define    wcurx(w)    ((w)->_curx)
  180. #define    wbegy(w)    ((w)->_begy)    /* window offset from origin */
  181. #define    wbegx(w)    ((w)->_begx)
  182. #define    wlines(w)    ((w)->_maxy)    /* # lines/cols in window w */
  183. #define    wcols(w)    ((w)->_maxx)
  184. #define    cursrow()    wcury(curscr)    /* current (y,x) on screen */
  185. #define    curscol()    wcurx(curscr)
  186.  
  187. /* stuff dependent on the version of curses */
  188. #ifdef TERMINFO
  189. #undef GAGMEKEYPAD
  190. #ifdef FASTTERMINFO
  191. #undef CURSEASSIST
  192. #endif
  193. #undef wlines
  194. #undef wcols
  195. #define    wlines(w)    ((w)->_maxy+1)    /* # lines/cols in window w */
  196. #define    wcols(w)    ((w)->_maxx+1)
  197. #include <term.h>
  198. /* undefine one of the more annoying definitions in term.h */
  199. #ifdef lines
  200. #undef lines
  201. #endif
  202. extern WINDOW *newscr;
  203. #define    Untouchwin(wp)    untouchwin(wp),untouchwin(newscr)
  204. #ifdef CURSEASSIST
  205. /* curseassist cheats big */
  206. #define    Cmove(y,x)    wmove(curscr,y,x),wmove(newscr,y,x)
  207. #define    Cinsertln()    winsertln(curscr),winsertln(newscr)
  208. #define    Cdeleteln()    wdeleteln(curscr),wdeleteln(newscr)
  209. #endif
  210. #else
  211. extern int *_putchar();
  212. #define    putp            _puts
  213. #define    enter_ca_mode        TI
  214. #define    cursor_address        CM
  215. #define    flash_screen        VB
  216. #define    enter_standout_mode    SO
  217. #define    exit_standout_mode    SE
  218. #define    move_standout_mode    MS
  219. #define    insert_line        AL
  220. #define    delete_line        DL
  221. #define    change_scroll_region    CS
  222. #define    scroll_reverse        SR
  223. #define    save_cursor        SC
  224. #define    restore_cursor        RC
  225. #define    insert_character    IC
  226. #define    insert_null_glitch    IN
  227. #define    enter_insert_mode    IM
  228. #define    exit_insert_mode    EI
  229. #define    delete_character    DC
  230. #define    scroll_forward        NL
  231. #define    cursor_down        DO
  232. #define    cursor_up        UP
  233. #define    Untouchwin(wp)    untouchwin(wp)
  234. #ifdef CURSEASSIST
  235. /* curseassist cheats big */
  236. #define    Cmove(y,x)    wmove(curscr,y,x)
  237. #define    Cinsertln()    winsertln(curscr)
  238. #define    Cdeleteln()    wdeleteln(curscr)
  239. #endif
  240. #endif
  241.  
  242. /* key pad atrocities follow */
  243. extern char tty_text[], keycap[];
  244. extern int tty_textlen, tty_backcnt;
  245. #ifndef KEY_BACKSPACE
  246. #define    KEY_BACKSPACE    0401
  247. #define    KEY_UP        0402
  248. #define    KEY_DOWN    0403
  249. #define    KEY_LEFT    0404
  250. #define    KEY_RIGHT    0405
  251. #define    KEY_HOME    0406
  252. #endif
  253. #ifndef GAGMEKEYPAD
  254. #define    tty_getch    tty_realgetch
  255. #endif
  256.  
  257. /*
  258.  * The number of active windows is limited by the number of
  259.  * open files a process (i.e., main) may have,
  260.  * the number of processes a user or the whole system can have,
  261.  * and (on an 11 but not a VAX) the memory for the per-window curses buffers.
  262.  * Also, window names are limited to 0..9, i.e. at most 10 windows.
  263.  */
  264. #define    MAXWINDOWS    10    /* windows #0..#9 */
  265.  
  266. #define    ESC        '\033'    /* char for virtual terminal functions */
  267. #define    CANCEL1        '\033'    /* char to cancel wm command */
  268. #define    CANCEL2        '\177'    /* char to cancel wm command */
  269.  
  270. #define    MINWINDOW    1    /* change this to 0 to permit window #0 */
  271. #define    iswindow(w) ((w)>=MINWINDOW && (w)<MAXWINDOWS && (win[w].flags&INUSE))
  272. #define    ctoi(c)        ((c)-'0')    /* convert ascii digit to int */
  273. #define    itoc(i)        ((i)+'0')    /* convert int to ascii digit */
  274.  
  275. /*
  276.  * Global data with miscellaneous information about each window
  277.  */
  278. struct win_struct
  279. {
  280.     int flags;            /* window status bits */
  281. #define    INUSE    001    /* window is in use */
  282. #define    XFLEX    002    /* # of columns is COLS (depends on terminal type) */
  283. #define    YFLEX    004    /* # of rows    is ROWS ( ""     ""    ""     "" ) */
  284. #define    FAST    010    /* window can scroll 'quickly' (not redrawn) */
  285. #define    BROWSE    020    /* window is in 'browse' mode */
  286. #define    BLOCKED    040    /* window updates are being delayed */
  287.     int next;            /* next window in list */
  288.     char covers[MAXWINDOWS];    /* TRUE for windows we're on top of */
  289.     WINDOW *wptr;        /* ptr to small curses win to be displayed */
  290.     WINDOW *boxbot, *boxtop;    /* ptrs to curses wins for box, or NULL */
  291.     WINDOW *boxright, *boxleft;    /* ptrs to curses wins for box, or NULL */
  292.     char pend[4];        /* characters in partial escape sequence */
  293.     int pid;            /* pid of this window's shell */
  294.     int pty;            /* fildes of pty to/from this win's shell */
  295. };
  296.  
  297. /*
  298.  * Handy macros
  299.  */
  300. #define    MAX(a,b)    ((a)>=(b)? (a): (b))
  301. #define    MIN(a,b)    ((a)<=(b)? (a): (b))
  302.  
  303. /*
  304.  * External variables.
  305.  */
  306. extern struct win_struct win[];    /* array of windows */
  307. extern int botw, topw, lastw;    /* bottom, top, last window */
  308. extern int prefix;        /* WM command prefix character */
  309. extern char savefile[];        /* name of save/restore file */
  310. extern char shellname[];    /* name of shell */
  311. extern char shellpgm[];        /* pathname of shell */
  312. extern int configflag;        /* true if window config. has changed */
  313. extern time_t msgbirth;        /* time last message was displayed */
  314. #ifndef TERMINFO
  315. extern char *change_scroll_region, *save_cursor, *restore_cursor;
  316. extern char *set_window;
  317. #endif
  318. extern int has_scroll_window, has_scroll_region, has_insdel_line;
  319.  
  320. /*
  321.  * Functions returning a non-int value
  322.  */
  323. XFILE *fopen();
  324. char *sprintf(), *strcpy(), *strcat(), *rindex(), *getenv();
  325. char *mkprint(), *termcap(), *WPrompt(), *plural();
  326. double *Malloc();    /* if only malloc were declared this way */
  327.  
  328. #define    alloc(n,type)    ((type*)Malloc((unsigned)((n)*sizeof(type))))
  329. SHAR_EOF
  330. if test 6227 -ne "`wc -c < 'wm.h'`"
  331. then
  332.     echo shar: error transmitting "'wm.h'" '(should have been 6227 characters)'
  333. fi
  334. fi # end of overwriting check
  335. echo shar: extracting "'cmd.c'" '(7983 characters)'
  336. if test -f 'cmd.c'
  337. then
  338.     echo shar: will not over-write existing file "'cmd.c'"
  339. else
  340. sed 's/^X//' << \SHAR_EOF > 'cmd.c'
  341. /*
  342.  *************
  343.  * DISTRIBUTION NOTICE  July 30 1985
  344.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  345.  *        Research Triangle Institute, (919) 541-7005.
  346.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  347.  *        Naval Research Laboratory, (202) 767-3365.
  348.  * No claims or warranties of any sort are made for this distribution.
  349.  * General permission is granted to copy, but not for profit,
  350.  * any of this distribution, provided that this notice
  351.  * is always included in the copies.
  352.  *************
  353.  */
  354. /*
  355.  * Command interpreter for WM.
  356.  */
  357.  
  358. #include "wm.h"
  359.  
  360. /*
  361.  * Command definitions
  362.  */
  363. # define DUMPWINDOW    'd'    /* dump contents of current window to file */
  364. # define FITWINDOW    'f'    /* Find best unobscured place for a window */
  365. # define HELP2        'h'    /* Command summary */
  366. # define HELP1        '?'    /* Command summary */
  367. # define IDENTWINDOW    'i'    /* print name of current window */
  368. # define KILLWINDOW    'k'    /* get rid of this window forever */
  369. # define LASTWINDOW    'l'    /* change to Last-used window */
  370. # define MOVEWINDOW    'm'    /* Move locn and/or change size of window */
  371. # define NEWWINDOW    'n'    /* make New window */
  372. # define PREFIX        'p'    /* change prefix character */
  373. # define QUIT        'q'    /* close up everything and Quit */
  374. # define REDRAW        'r'    /* Redraw all windows */
  375. # define SAVEWINDOWS    's'    /* save current window configuration */
  376. # define TERMCAP    't'    /* Reset $TERM and $TERMCAP of current window */
  377. # define SUSPEND    'z'    /* suspend wm */
  378. # define NOOP1        ' '    /* no-op */
  379. # define NOOP2        '\n'    /* no-op */
  380. # define NOOP3        '\r'    /* no-op */
  381.  
  382.  
  383. /*
  384.  * Execute a WM command.
  385.  */
  386. docmd(cmd)
  387.  
  388. int cmd;    /* IN: command code */
  389. {
  390.     register int w, tmpw;
  391.     int begline, begcol, lines, cols;    /* window parameters */
  392.     char *s;
  393.     register WINDOW *wp;
  394.  
  395.  
  396.     switch (cmd)
  397.     {
  398.     case CANCEL1:
  399.     case CANCEL2:
  400.     showmsg("Canceled.");
  401.     break;
  402.  
  403.     case NEWWINDOW:
  404.     tmpw = topw;
  405.     if ((w = GetSlot()) < 0) {
  406.         showmsg("Sorry, can't create any more windows.");
  407.         break;
  408.     }
  409.     if (NewWindow(w,LINES-1,COLS,0,0))
  410.         break;
  411.     WListAdd(w);
  412.     if (getbounds(w, TRUE) != 0)
  413.         break;    /* getbounds will have freed the window */
  414.     lastw = tmpw;
  415.     showmsg("Created new window #%d.", w);
  416.     winchanged(w);
  417.     break;
  418.  
  419.     case '0':
  420.     case '1':
  421.     case '2':
  422.     case '3':
  423.     case '4':
  424.     case '5':
  425.     case '6':
  426.     case '7':
  427.     case '8':
  428.     case '9':
  429.     w = ctoi(cmd);
  430.     if ( ! iswindow(w))
  431.         showmsg("No such window #%d.", w);
  432.     else if (w == topw)
  433.         showmsg("You're already in window #%d.", w);
  434.     else
  435.     {
  436.         lastw = topw;
  437.         WListDelete(w);
  438.         WListAdd(w);
  439.         RedrawScreen();
  440.         showmsg("Changed to window #%d.", w);
  441.     }
  442.     break;
  443.  
  444.     case LASTWINDOW:
  445.     if (iswindow(lastw) && lastw!=topw)
  446.     {
  447.         w=lastw;
  448.         lastw=topw;
  449.         WListDelete(w);
  450.         WListAdd(w);
  451.         RedrawScreen();
  452.         showmsg("Changed back to window #%d.", w);
  453.     }
  454.     else
  455.         showmsg("No last window.");
  456.     break;
  457.  
  458.     case MOVEWINDOW:
  459.     w = topw;
  460.     wp = win[w].wptr;
  461.     lines = wlines(wp); cols = wcols(wp);
  462.     begline = wbegy(wp); begcol = wbegx(wp);
  463.     if (getbounds(w, FALSE) != 0)
  464.         break;
  465.     wp = win[w].wptr;
  466.     if (lines == wlines(wp) && cols == wcols(wp)) {
  467.         if (begline == wbegy(wp) && begcol == wbegx(wp)) {
  468.         showmsg("Window unchanged.");
  469.         break;
  470.         }
  471.     }
  472.     else
  473.         SetTerm(w, 2);
  474.     showmsg("Moved window #%d.", w);
  475.     winchanged(w);
  476.     break;
  477.  
  478.     case FITWINDOW:
  479.     showmsg("Fit which window?");
  480.     if ((w = askwindow()) < 0)
  481.         break;
  482.     if (fitwindow(w, &lines, &cols, &begline, &begcol) < 0) {
  483.         showmsg("Sorry, cannot find unobscured placement.");
  484.         break;
  485.     }
  486.     wp = win[w].wptr;
  487.     tmpw = 1;    /* shameless misuse of variable */
  488.     if (lines == wlines(wp) && cols == wcols(wp)) {
  489.         tmpw = 0;
  490.         if (begline == wbegy(wp) && begcol == wbegx(wp)) {
  491.         showmsg("Window already has best fit.");
  492.         break;
  493.         }
  494.     }
  495.     if (NewWindow(w,lines,cols,begline,begcol)) {
  496.         WListDelete(w);
  497.         break;
  498.     }
  499.     if (tmpw)
  500.         SetTerm(w, 2);
  501.     RedrawScreen();
  502.     showmsg("Moved window #%d.", w);
  503.     winchanged(w);
  504.     break;
  505.  
  506.     case KILLWINDOW:
  507.     showmsg("Kill which window?"); /* enter window name */
  508.     if ((w = askwindow())  < 0)
  509.         break;
  510.     if (w==topw)
  511.     {
  512.         showmsg("Can't kill the current window.");
  513.         break;
  514.     }
  515.     WListDelete(w); KillShell(w); FreeWindow(w);
  516.     RedrawScreen();
  517.     showmsg("Killed window #%d.", w);
  518.     if (w==lastw) lastw = -1;
  519.     configflag = TRUE;
  520.     break;
  521.  
  522.     case IDENTWINDOW:
  523.     IdentWindows();
  524.     break;
  525.  
  526.     case DUMPWINDOW:
  527.     if ((s = WPrompt("dump file", "wmdump")) == NULL)
  528.         break;
  529.     else if (DumpWindow(topw, s) == 0)
  530.         showmsg("Dumped contents of top window to file '%s'.", s);
  531.     else
  532.         showmsg("Sorry, can't open dump file '%s'.", s);
  533.     break;
  534.  
  535.     case REDRAW:
  536.     ClearScreen();
  537.     RedrawScreen();
  538.     break;
  539.  
  540.     case TERMCAP:
  541.     SetTerm(topw, 3);
  542.     break;
  543.  
  544.     case HELP1:
  545.     case HELP2:
  546.     ClearScreen();
  547.     helpmsg();
  548.     (void) tty_getch();
  549.     ClearScreen();
  550.     RedrawScreen();
  551.     break;
  552.  
  553.     case PREFIX:
  554.     showmsg("Enter new WM prefix character.");
  555.     prefix = tty_getch();
  556.     showmsg("New WM prefix character is '%s'.", mkprint(prefix));
  557.     configflag = TRUE;
  558.     break;
  559.  
  560.     case SUSPEND:
  561.     suspend();
  562.     break;
  563.  
  564.     case SAVEWINDOWS:
  565.     if ((s = WPrompt("save file", savefile))  == NULL)
  566.         break;
  567.     (void) strcpy(savefile, s);
  568.     if (Save(savefile) != 0)
  569.     {
  570.         showmsg("Saved current window configuration in '%s'.", savefile);
  571.         configflag = FALSE;
  572.     }
  573.     else showmsg("Sorry, can't save current window configuration.");
  574.     break;
  575.  
  576.     case QUIT:
  577.     return(TRUE);
  578.  
  579.     case NOOP1:
  580.     case NOOP2:
  581.     case NOOP3:
  582.     break;
  583.  
  584.     default:
  585.     showmsg("Invalid command '%s': use 'h' command for help.",mkprint(cmd));
  586.     break;
  587.     }
  588.  
  589.     return(FALSE);
  590. }
  591.  
  592. /*
  593.  * suspend w/ job control if using csh, otherwise spawn subshell.
  594.  * This could be integrated into curses tstp(),
  595.  * but I wasn't sure that could be done correctly,
  596.  * since it is impossible(?) to determine if the parent shell
  597.  * knows job control.
  598.  */
  599. suspend()
  600. {
  601.     register int rc;
  602. #ifndef TERMINFO
  603.     register int ttyflags;
  604. #endif
  605.  
  606.     /* If wm's parent is init, then we better not suspend with TSTP!
  607.      * Unfortunately, this heuristic fails if the user used rlogin,
  608.      * since wm's parent would then be rlogind.  We can only hope
  609.      * the user knows what he is doing.
  610.      */
  611.     if (getppid() != 1
  612.      && (rc = strlen(shellname)) >= 3
  613.      && strcmp(shellname+rc-3, "csh") == 0) {
  614.     showmsg("Suspending.");
  615.     tstp();
  616.     showmsg("WM resumed.");
  617.     return;
  618.     }
  619.  
  620.     showmsg("Spawning a sub-shell ...");
  621.     (void) movecursor(LINES-1, 0);
  622. #ifndef TERMINFO
  623.     ttyflags = _tty.sg_flags;
  624. #endif
  625.     endwin();
  626.     putchar('\n');    /* scroll up, for neatness */
  627.     (void) fflush(stdout);
  628.  
  629.     rc = system(shellpgm);
  630. #ifdef TERMINFO
  631. #ifdef BUGGYTERMINFO
  632.     /* Alas, buggyterminfo apparently does not re-remember the virgin state
  633.      * or correct for a baud-rate change */
  634. #endif
  635.     fixterm();
  636. #else
  637.     savetty();    /* re-remember the virgin state */
  638.     _tty.sg_flags = ttyflags;
  639.     (void) ioctl(_tty_ch, TIOCSETN, (char *)&_tty);
  640. #endif
  641.     if (enter_ca_mode)
  642.     putp(enter_ca_mode);
  643.     wrefresh(curscr);
  644.     /* we could diagnose things better here */
  645.     if (rc == 127)
  646.     showmsg("Cannot spawn a shell!");
  647.     else
  648.     showmsg("Returning to WM.");
  649. }
  650.  
  651. /*
  652.  * Set 'configflag' to indicate change affecting wmrc file.
  653.  * If this window is full-width or full-length,
  654.  * set the corresponding 'flex' flag.
  655.  * Warn user if this is a 'slow' window.
  656.  */
  657. winchanged(w)
  658. register int w;
  659. {
  660.     register WINDOW *wp;
  661.     static int full_width_warning = FALSE;
  662.  
  663.     configflag = TRUE;
  664.     win[w].flags &= ~(XFLEX|YFLEX);
  665.     wp = win[w].wptr;
  666.     if (wcols(wp) == COLS)
  667.     win[w].flags |= XFLEX;
  668.     if (wlines(wp) == LINES-1)
  669.     win[w].flags |= YFLEX;
  670.     WObscure();        /* recompute obscured window info */
  671.     if (!(win[w].flags&FAST)) {
  672.     if (wcols(wp) != COLS) {
  673.         showmsg("\007Non full-width window #%d will scroll slowly!", w);
  674.         return;
  675.     }
  676.     if (full_width_warning)
  677.         return;
  678.     full_width_warning = TRUE;
  679.     showmsg("\007This terminal scrolls split-screen windows slowly.");
  680.     }
  681. }
  682. SHAR_EOF
  683. if test 7983 -ne "`wc -c < 'cmd.c'`"
  684. then
  685.     echo shar: error transmitting "'cmd.c'" '(should have been 7983 characters)'
  686. fi
  687. fi # end of overwriting check
  688. echo shar: extracting "'curses.c'" '(11058 characters)'
  689. if test -f 'curses.c'
  690. then
  691.     echo shar: will not over-write existing file "'curses.c'"
  692. else
  693. sed 's/^X//' << \SHAR_EOF > 'curses.c'
  694. /*
  695.  *************
  696.  * DISTRIBUTION NOTICE  July 30 1985
  697.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  698.  *        Research Triangle Institute, (919) 541-7005.
  699.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  700.  *        Naval Research Laboratory, (202) 767-3365.
  701.  * No claims or warranties of any sort are made for this distribution.
  702.  * General permission is granted to copy, but not for profit,
  703.  * any of this distribution, provided that this notice
  704.  * is always included in the copies.
  705.  *************
  706.  */
  707. /*
  708.  * curses.c  R. Jacob
  709.  */
  710.  
  711. #include "wm.h"
  712.  
  713. static WINDOW *mw=NULL;        /* message window */
  714. static WINDOW *cmw=NULL;    /* blank message window */
  715. time_t msgbirth = 0;
  716.  
  717.  
  718. /*
  719.  * Set up win structure and associated junk for new window w.
  720.  * Returns 0 if sucessful, else -1.
  721.  */
  722. NewWindow(w, lines, cols, begline, begcol)
  723.  
  724. register int w;
  725. int lines, cols, begline, begcol;
  726. {
  727.     register WINDOW *wp, *owp;
  728.  
  729.  
  730.     if ((wp=newwin(lines,cols,begline,begcol)) == NULL) {
  731.     showmsg("\007Cannot %sconstruct window #%d!.",
  732.         ((win[w].flags&INUSE)? "re": ""), w);
  733.     FreeWindow(w);
  734.     return(-1);
  735.     }
  736.     leaveok(wp, TRUE);
  737.  
  738.     /* If the window is already in use, copy old window to new one
  739.      * anchored at bottom left of the windows.
  740.      * We move the bottom left of both windows to the bottom left
  741.      * of the screen, overwrite, then move the windows back.
  742.      * (Actually, we do not bother to move the old window back.)
  743.      */
  744.     if (win[w].flags&INUSE) {
  745.     owp = win[w].wptr;
  746.     mvwin(owp, LINES-wlines(owp), 0);
  747.     mvwin(wp, LINES-wlines(wp), 0);
  748.     overwrite(owp, wp);
  749.     mvwin(wp, begline, begcol);
  750.     wmove(wp, wcury(owp) + (wlines(wp)-wlines(owp)), wcurx(owp));
  751.     FreeWindow(w);
  752.     }
  753.  
  754.     win[w].wptr = wp;
  755.  
  756.     if (MakeBorders(w) != 0)
  757.     {
  758.     showmsg("\007Cannot construct borders for window #%d!.", w);
  759.     FreeWindow(w);
  760.     return(-1);
  761.     }
  762.  
  763.     win[w].flags |= INUSE;
  764.     if (has_scroll_window
  765.      || (cols == COLS
  766.       && (has_scroll_region || has_insdel_line || lines == LINES-1)))
  767.     win[w].flags |= FAST;
  768.  
  769.     return(0);
  770. }
  771.  
  772. /*
  773.  * Deallocate win structure and associated junk.
  774.  */
  775. XFreeWindow(w)
  776.  
  777. register int w;
  778. {
  779.     win[w].flags = 0;
  780.  
  781.     if (win[w].wptr)     {delwin(win[w].wptr);     win[w].wptr = 0;}
  782.     if (win[w].boxbot)     {delwin(win[w].boxbot);   win[w].boxbot = 0;}
  783.     if (win[w].boxtop)     {delwin(win[w].boxtop);   win[w].boxtop = 0;}
  784.     if (win[w].boxright) {delwin(win[w].boxright); win[w].boxright = 0;}
  785.     if (win[w].boxleft)     {delwin(win[w].boxleft);  win[w].boxleft = 0;}
  786. }
  787.  
  788. #ifdef notdef
  789. /*
  790.  * Redraw window w.
  791.  */
  792. RedrawWindow(w)
  793.  
  794. register int w;
  795. {
  796.     register WINDOW *wp;
  797.  
  798.     if (!iswindow(w))
  799.     return;
  800.     if (wp=win[w].wptr)     { touchwin(wp); wrefresh(wp); }
  801.     if (wp=win[w].boxbot)   { touchwin(wp); wrefresh(wp); }
  802.     if (wp=win[w].boxtop)   { touchwin(wp); wrefresh(wp); }
  803.     if (wp=win[w].boxright) { touchwin(wp); wrefresh(wp); }
  804.     if (wp=win[w].boxleft)  { touchwin(wp); wrefresh(wp); }
  805. }
  806. #endif
  807.  
  808. /*
  809.  * Redraw the entire screen.
  810.  * Uses Curses' standard screen, stdscr.
  811.  */
  812. RedrawScreen()
  813. {
  814.     register int w, base;
  815.     register WINDOW *wp;
  816.  
  817.     /* speed hack: start with the topmost full-screen window.
  818.      * (Smarter hacks come to mind, but this one is easy.)
  819.      */
  820.     base = botw;
  821.     for (w=base; w>=0; w=win[w].next)
  822.     if ((wp = win[w].wptr) && wcols(wp) == COLS && wlines(wp) >= LINES-1)
  823.         base = w;
  824.  
  825.     werase(stdscr);
  826.  
  827.      /* Write contents of all windows into stdscr, then refresh.
  828.       */
  829.     for (w=base; w>=0; w=win[w].next)
  830.     {
  831.     if (wp=win[w].wptr)     overwrite(wp, stdscr);
  832.     if (wp=win[w].boxtop)   overwrite(wp, stdscr);
  833.     if (wp=win[w].boxbot)   overwrite(wp, stdscr);
  834.     if (wp=win[w].boxright) overwrite(wp, stdscr);
  835.     if (wp=win[w].boxleft)  overwrite(wp, stdscr);
  836.     }
  837.  
  838.     if (msgbirth)
  839.     overwrite(mw, stdscr);
  840.     touchwin(stdscr);
  841.     wrefresh(stdscr);
  842.     RestoreCursor();
  843. }
  844.  
  845. /*
  846.  * Identify windows.
  847.  * Draw each window in turn, from bottom to top.
  848.  * Uses Curses' standard screen, stdscr.
  849.  */
  850. IdentWindows()
  851. {
  852.     register int w;    /* window index */
  853.     register WINDOW *wp;
  854.     register int canceled=FALSE; /* TRUE if user cancels this command */
  855.     register int c;
  856.  
  857.  
  858.      /* Erase the screen (and stdscr).
  859.       */
  860.     ClearScreen();
  861.  
  862.      /* Write contents of each window into stdscr, then refresh.
  863.       */
  864.     for (w=botw; w>=0; w=win[w].next)
  865.     {
  866.     if (wp=win[w].wptr)     overwrite(wp, stdscr);
  867.     if (wp=win[w].boxtop)   overwrite(wp, stdscr);
  868.     if (wp=win[w].boxbot)   overwrite(wp, stdscr);
  869.     if (wp=win[w].boxright) overwrite(wp, stdscr);
  870.     if (wp=win[w].boxleft)  overwrite(wp, stdscr);
  871.  
  872.     if (canceled)
  873.         continue;
  874.  
  875. #ifdef BUGGYTERMINFO
  876.     /* buggyterminfo seems to require this */
  877.     touchwin(stdscr);
  878. #endif
  879.     wrefresh(stdscr);
  880.  
  881.     if (w != topw)
  882.     {
  883.         showmsg("Window #%d.  Hit any key to see next window.", w);
  884.         c = tty_getch();
  885.         if (c == CANCEL1  ||  c == CANCEL2)
  886.         {
  887.         showmsg("Canceled.");
  888.         canceled = TRUE;
  889.         }
  890.     }
  891.  
  892.     else
  893.     {
  894.         showmsg("Window #%d (top window).  Hit any key to continue.", w);
  895.         (void) tty_getch();
  896.     }
  897.     }
  898.  
  899.     if (canceled)
  900.     wrefresh(stdscr);
  901.     RestoreMsg();
  902.     RestoreCursor();
  903. }
  904.  
  905. /*
  906.  * Show message s on bottom of screen.
  907.  */
  908. /*VARARGS1*/
  909. showmsg(s, arg1, arg2)
  910.  
  911. register char *s;
  912. {
  913.     char buf[256];
  914.  
  915.      /* Initialize message window first time 'round.
  916.       */
  917.     if (mw == NULL) {
  918.     mw=newwin(1, 0, LINES-1, 0);
  919.     cmw=newwin(1, 0, LINES-1, 0);
  920.     if (!mw || !cmw) {
  921.         fprintf(stderr, "Cannot create message window!\n\r");
  922.         Shutdown(1);
  923.     }
  924.     leaveok(cmw, TRUE);
  925.     werase(cmw);
  926.     /* (leaveok for mw & cursor positioning for prompts needs thought) */
  927.     wstandout(mw);
  928.     }
  929.  
  930. #ifdef notdef
  931.     /* pause to let user ponder a previous message */
  932.     if (msgbirth && *s && (t = 2-abs(msgbirth - time((time_t *)0))) > 0)
  933.     sleep((unsigned int)t);
  934. #endif
  935.  
  936.     /* Format the message */
  937.     (void) sprintf(buf, s, arg1, arg2);
  938.     s = buf;
  939.     s[wcols(mw)-1] = '\0';        /* make sure it fits */
  940.  
  941.     /* hack to honk but once */
  942.     if (*s == '\007') {
  943.     flash();
  944.     s++;
  945.     }
  946.     werase(mw);
  947.     waddstr(mw, s);
  948.     touchwin(mw);
  949.     wrefresh(mw);
  950.  
  951.     msgbirth = s[0]? time((time_t *)0): 0;
  952. }
  953.  
  954. ZapMsgLine()
  955. {
  956.     if (msgbirth) {
  957.     touchwin(cmw);
  958.     wrefresh(cmw);
  959.     }
  960. }
  961.  
  962. RestoreMsg()
  963. {
  964.     if (msgbirth) {
  965.     touchwin(mw);
  966.     wrefresh(mw);
  967.     }
  968. }
  969.  
  970. /*
  971.  * Restore cursor in top window.
  972.  */
  973. RestoreCursor()
  974. {
  975.     register WINDOW *wp;    /* pointer to top window */
  976.  
  977.     wp = win[topw].wptr;
  978.     if (movecursor(wbegy(wp)+wcury(wp), wbegx(wp)+wcurx(wp)))
  979.     (void) fflush(stdout);
  980. }
  981.  
  982. /*
  983.  * Clear the whole screen
  984.  */
  985. ClearScreen()
  986. {
  987.     wclear(stdscr);
  988.     wrefresh(stdscr);
  989. }
  990.  
  991. /*
  992.  * Creates windows containing
  993.  * a border to surround window w
  994.  * and puts pointer to the new windows
  995.  * into proper places in global win[].
  996.  * Borders appear in standout mode if
  997.  * terminal has that capability.
  998.  * Returns 0 if sucessful, else -1.
  999.  */
  1000. MakeBorders(w)
  1001.  
  1002. register int w;        /* make borders for this window */
  1003. {
  1004.     int left, right, top, bottom;    /* border flags */
  1005.     int begx, begy, cols, lines;    /* window dimensions */
  1006.     register WINDOW *wp;        /* window pointer */
  1007.     register int i;            /* index */
  1008.  
  1009.  
  1010.      /* Get window dimensions.
  1011.       */
  1012.     wp = win[w].wptr;
  1013.     begx =  wbegx(wp);
  1014.     begy =  wbegy(wp);
  1015.     cols =  wcols(wp);
  1016.     lines = wlines(wp);
  1017.  
  1018.  
  1019.      /* Determine which sides of the window need borders.
  1020.       */
  1021.     left   = (begx > 0);
  1022.     right  = (begx+cols < COLS);
  1023.     top    = (begy > 0);
  1024.     bottom = (begy+lines < LINES-1); /* bottom line for msgs */
  1025.  
  1026.     if (top)
  1027.     --begy, ++lines;
  1028.     if (bottom)
  1029.     lines++;
  1030.     
  1031.  
  1032.      /* Make left border using '>'.
  1033.       */
  1034.     if (left)
  1035.     {
  1036.     if ((win[w].boxleft = wp = newwin(lines,1,begy,begx-1))  == NULL)
  1037.         return(-1);
  1038.     leaveok(wp, TRUE);
  1039.     wstandout(wp);
  1040.     for (i=0; i<lines; i++)
  1041.         waddch(wp, '>');
  1042.     }
  1043.     
  1044.  
  1045.      /* Make right border using '<'.
  1046.       */
  1047.     if (right)
  1048.     {
  1049.     if ((win[w].boxright = wp = newwin(lines,1,begy,begx+cols))  == NULL)
  1050.         return(-1);
  1051.     leaveok(wp, TRUE);
  1052.     wstandout(wp);
  1053.     for (i=0; i<lines; i++)
  1054.         waddch(wp, '<');
  1055.     }
  1056.  
  1057.  
  1058.      /* Make top border using window number.
  1059.       */
  1060.     if (top)
  1061.     {
  1062.     if ((win[w].boxtop = wp = newwin(1,cols,begy,begx))  == NULL)
  1063.         return(-1);
  1064.     leaveok(wp, TRUE);
  1065.     wstandout(wp);
  1066.     for (i=0; i<cols; i++)
  1067.         waddch(wp, itoc(w));
  1068.     }
  1069.  
  1070.  
  1071.      /* Make bottom border using window number.
  1072.       */
  1073.     if (bottom)
  1074.     {
  1075.     if ((win[w].boxbot = wp = newwin(1,cols,begy+lines-1,begx))  == NULL)
  1076.         return(-1);
  1077.     leaveok(wp, TRUE);
  1078.     wstandout(wp);
  1079.     for (i=0; i<cols; i++)
  1080.         waddch(wp, itoc(w));
  1081.     }
  1082.  
  1083.     return(0);
  1084. }
  1085.  
  1086. /*
  1087.  * Dump.
  1088.  * Dump the contents of the current window to file 'wmdump'
  1089.  * in the current directory.
  1090.  * Returns 0 on sucessful completion, -1 otherwise.
  1091.  */
  1092. DumpWindow(w, dumpfile)
  1093.  
  1094. int w;        /* number of window we're to dump */
  1095. char *dumpfile;    /* file we're dumping to */
  1096. {
  1097.     register WINDOW *wp;    /* top window */
  1098.     register FILE *dfp;        /* dump file pointer */
  1099.     register int line, col;    /* current line, column of window */
  1100.     register int lastcol;    /* column of rightmost non-blank */
  1101.     int oldy, oldx;        /* saved cursor position */
  1102.  
  1103.     if ((dfp = fopen(dumpfile, "w"))  == NULL)
  1104.     return(-1);
  1105.  
  1106.     wp = win[w].wptr;
  1107.     getyx(wp, oldy, oldx);
  1108.     for (line = 0; line < wlines(wp); line++)
  1109.     {
  1110.     lastcol = wcols(wp);
  1111.     while (--lastcol >= 0)
  1112.         if (toascii(mvwinch(wp, line, lastcol)) != ' ')
  1113.         break;
  1114.     for (col = 0; col <= lastcol; col++)
  1115.         putc(toascii(mvwinch(wp, line, col)),  dfp);
  1116.     putc('\n', dfp);
  1117.     }
  1118.     (void) fclose(dfp);
  1119.     wmove(wp, oldy, oldx);
  1120.     return(0);
  1121. }
  1122.  
  1123. #define BUFLEN        80
  1124.  
  1125. /* Prompt user for a string.
  1126.  */
  1127. char *
  1128. WPrompt(prompt, dflt)
  1129.  
  1130. char *prompt;    /* prompt */
  1131. char *dflt;    /* default response */
  1132. {
  1133.     register int c;        /* character in string */
  1134.     static char buf[BUFLEN+1];    /* string buffer */
  1135.     register int i=0;        /* buffer index */
  1136.     int maxlen, x;        /* how long can string be? */
  1137.  
  1138.      /* Print prompt and default response
  1139.       * on bottom line of screen.
  1140.       */
  1141.     showmsg("%s? [%s] ", prompt, dflt);
  1142.  
  1143.      /* Determine length of longest string
  1144.       * that will fit in window.
  1145.       */
  1146.     x = wcurx(mw);
  1147.     maxlen = (BUFLEN < wcols(mw)-2-x  ?  BUFLEN  :  wcols(mw)-2-x);
  1148.  
  1149.  
  1150.      /* Read string. Process line kill & backspace chars.
  1151.       */
  1152.     while ((c = tty_getch()) != EOF && c != '\n' && c != '\r')
  1153.     {
  1154.     if (c==CANCEL1 || c==CANCEL2)    /* cancel */
  1155.     {
  1156.         showmsg("Canceled.");
  1157.         return(NULL);
  1158.     }
  1159.     if (c==erasechar() || c == KEY_BACKSPACE || c == KEY_LEFT)
  1160.     {
  1161.         if (i > 0)
  1162.         {
  1163.         i--;
  1164.         waddstr(mw, "\b \b");
  1165.         }
  1166.     }
  1167.     else if (c == killchar())
  1168.     {
  1169.         i = 0;
  1170.         wmove(mw, 0, x);
  1171.         wclrtoeol(mw);
  1172.     }
  1173.     else if (i > maxlen)        /* is string too long? */
  1174.         flash();
  1175.     else if (isspace(c) || !isprint(c)) /* is character inappropriate? */
  1176.         flash();
  1177.     else                /* regular char: add to string */
  1178.     {
  1179.         waddch(mw, c);
  1180.         buf[i++] = c;
  1181.     }
  1182.  
  1183.     wrefresh(mw);
  1184.     }
  1185.  
  1186.  
  1187.      /* If user didn't respond, just return default response.
  1188.       */
  1189.     if (i == 0)
  1190.     strcpy(buf, dflt);
  1191.     else
  1192.     buf[i] = '\0';
  1193.  
  1194.  
  1195.     return(buf);
  1196. }
  1197. SHAR_EOF
  1198. if test 11058 -ne "`wc -c < 'curses.c'`"
  1199. then
  1200.     echo shar: error transmitting "'curses.c'" '(should have been 11058 characters)'
  1201. fi
  1202. fi # end of overwriting check
  1203. echo shar: extracting "'getch.c'" '(6283 characters)'
  1204. if test -f 'getch.c'
  1205. then
  1206.     echo shar: will not over-write existing file "'getch.c'"
  1207. else
  1208. sed 's/^X//' << \SHAR_EOF > 'getch.c'
  1209. /*
  1210.  *************
  1211.  * DISTRIBUTION NOTICE  July 30 1985
  1212.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  1213.  *        Research Triangle Institute, (919) 541-7005.
  1214.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  1215.  *        Naval Research Laboratory, (202) 767-3365.
  1216.  * No claims or warranties of any sort are made for this distribution.
  1217.  * General permission is granted to copy, but not for profit,
  1218.  * any of this distribution, provided that this notice
  1219.  * is always included in the copies.
  1220.  *************
  1221.  */
  1222. #include "wm.h"
  1223. #include <signal.h>
  1224.  
  1225. char keycap[200];    /* termcap entries for keypad functions */
  1226.  
  1227. int tty_backcnt;    /* number of pre-read terminal chars */
  1228. char tty_backbuf[10];    /* stack of pre-read chars */
  1229. char tty_text[10];    /* actual text corresponding to tty_getch code */
  1230. int tty_textlen;    /* strlen(tty_text) */
  1231.  
  1232. /*
  1233.  * Returns true iff a call to tty_realgetch would not block.
  1234.  */
  1235. tty_inputpending()
  1236. {
  1237.     long n;
  1238.  
  1239.     if (tty_backcnt > 0)
  1240.     return(TRUE);
  1241.     if (ioctl(0, (int)FIONREAD, (char *)&n) == 0 && n > 0)
  1242.     return(TRUE);
  1243.     return(FALSE);
  1244. }
  1245.  
  1246. /*
  1247.  * Read the next character from the terminal (or the backbuf),
  1248.  * return EOF if end of file, else (int)the_char, sans parity
  1249.  */
  1250. int
  1251. tty_realgetch()
  1252. {
  1253.     char c;
  1254.  
  1255.     if (tty_backcnt > 0)
  1256.     c = tty_backbuf[--tty_backcnt];
  1257.     else if (read(0, &c, 1) <= 0) {
  1258.     tty_text[0] = '\0';
  1259.     tty_textlen = 0;
  1260.     return(EOF);
  1261.     }
  1262.     c = toascii(c);
  1263.     tty_text[0] = c;
  1264.     tty_text[1] = '\0';
  1265.     tty_textlen = 1;
  1266.     return(c);
  1267. }
  1268.  
  1269. #ifdef GAGMEKEYPAD
  1270. init_keypad()
  1271. {
  1272.     register int i;
  1273.     register char *p;
  1274.     char buf1[10];
  1275.  
  1276.     if (p = getcap("ks"))
  1277.         putp(p);
  1278.     for (i=1,p = "kbkukdklkrkhk0k1k2k3k4k5k6k7k8k9"; *p; i++,p+= 2) {
  1279.         (void) sprintf(buf1, "%2.2s", p);
  1280.         add_to_try(buf1, i+0400);
  1281.     }
  1282. }
  1283.  
  1284. /*
  1285. **      add_to_try() (Copyright Pavel Curtis, see notice in hacks.c)
  1286. **
  1287. **      Construct the try for the current terminal's keypad keys.
  1288. **
  1289. */
  1290. struct try
  1291. {
  1292.     struct try      *child;     /* ptr to child.  NULL if none          */
  1293.     struct try      *sibling;   /* ptr to sibling.  NULL if none        */
  1294.     char            ch;         /* character at this node               */
  1295.     short           value;      /* code of string so far.  NULL if none */
  1296. };
  1297.  
  1298. static struct  try *newtry;
  1299.  
  1300. add_to_try(capname, code)
  1301. char    *capname;
  1302. int code;
  1303. {
  1304.     register struct try *ptr, *savedptr;
  1305.     register char *str, *s;
  1306.     static bool     out_of_memory = FALSE;
  1307.  
  1308.     str = getcap(capname);
  1309.     if (! str  ||  out_of_memory)
  1310.         return;
  1311.     strcat(keycap, capname); strcat(keycap, "=");
  1312.     for (s = str; *s; s++) {
  1313.         strcat(keycap, mkprint(*s));
  1314.     }
  1315.     strcat(keycap, ":");
  1316.     
  1317.     if (newtry != NULL)    
  1318.     {
  1319.         ptr = newtry;
  1320.         
  1321.         for (;;)
  1322.         {
  1323.         while (ptr->ch != *str  &&  ptr->sibling != NULL)
  1324.             ptr = ptr->sibling;
  1325.         
  1326.         if (ptr->ch == *str)
  1327.         {
  1328.             if (*(++str))
  1329.             {
  1330.             if (ptr->child != NULL)
  1331.                 ptr = ptr->child;
  1332.             else
  1333.                 break;
  1334.             }
  1335.             else
  1336.             {
  1337.             ptr->value = code;
  1338.             return;
  1339.             }
  1340.         }
  1341.         else
  1342.         {
  1343.             if ((ptr->sibling = alloc(1, struct try)) == NULL)
  1344.             {
  1345.             out_of_memory = TRUE;
  1346.             return;
  1347.             }
  1348.             
  1349.             savedptr = ptr = ptr->sibling;
  1350.             ptr->child = ptr->sibling = NULL;
  1351.             ptr->ch = *str++;
  1352.             ptr->value = NULL;
  1353.             
  1354.             break;
  1355.         }
  1356.         } /* end for (;;) */  
  1357.     }
  1358.     else    /* newtry == NULL :: First sequence to be added */
  1359.     {
  1360.         savedptr = ptr = newtry = alloc(1, struct try);
  1361.         
  1362.         if (ptr == NULL)
  1363.         {
  1364.         out_of_memory = TRUE;
  1365.         return;
  1366.         }
  1367.         
  1368.         ptr->child = ptr->sibling = NULL;
  1369.         ptr->ch = *(str++);
  1370.         ptr->value = NULL;
  1371.     }
  1372.     
  1373.         /* at this point, we are adding to the try.  ptr->child == NULL */
  1374.         
  1375.     while (*str)
  1376.     {
  1377.         ptr->child = alloc(1, struct try);
  1378.         
  1379.         ptr = ptr->child;
  1380.         
  1381.         if (ptr == NULL)
  1382.         {
  1383.         out_of_memory = TRUE;
  1384.         
  1385.         ptr = savedptr;
  1386.         while (ptr != NULL) 
  1387.         {
  1388.             savedptr = ptr->child;
  1389.             free((char *)ptr);
  1390.             ptr = savedptr;
  1391.         }
  1392.         
  1393.         return;
  1394.         }
  1395.         
  1396.         ptr->child = ptr->sibling = NULL;
  1397.         ptr->ch = *(str++);
  1398.         ptr->value = NULL;
  1399.     }
  1400.     
  1401.     ptr->value = code;
  1402.     return;
  1403. }
  1404.  
  1405. #include <setjmp.h>
  1406. static jmp_buf jmpbuf;
  1407.  
  1408. /*
  1409. **      tty_getch() (Copyright Pavel Curtis, see notice in hacks.c)
  1410. **
  1411. **      Get an input character, but take care of keypad sequences, returning
  1412. **      an appropriate code when one matches the input.  After each character
  1413. **      is received, set an alarm call.  If no more of the sequence
  1414. **      is received by the time the alarm goes off, pass through the sequence
  1415. **      gotten so far.
  1416. **
  1417. */
  1418. tty_getch()
  1419. {
  1420.     /* longjmp alert!  beware of register variables */
  1421.     register struct try  *ptr;
  1422.     int        ch;
  1423.     char        buffer[10];     /* Assume no sequences longer than 10 */
  1424.     char *bufp = buffer;
  1425.     int         (*oldsigalrm)();
  1426.     int         sigalrm();
  1427.     bool    alarmset;
  1428.  
  1429.     ptr = newtry;
  1430.     alarmset = FALSE;
  1431.     oldsigalrm = SIG_DFL;    /* to quiet lint */
  1432.     
  1433.     do
  1434.     {
  1435.         if (setjmp(jmpbuf))
  1436.         break;
  1437.         ch = tty_realgetch();
  1438.         if (ch != EOF)              /* returns EOF on error, too */
  1439.         *(bufp++) = ch;
  1440.         
  1441.         while (ptr != NULL  &&  ptr->ch != ch)
  1442.         ptr = ptr->sibling;
  1443.         
  1444.         if (ptr != NULL)
  1445.         {
  1446.         if (ptr->value != NULL)
  1447.         {
  1448.             if (alarmset) {
  1449.             (void) ualarm(0L);
  1450.             (void) signal(SIGALRM, oldsigalrm);
  1451.             }
  1452.             tty_textlen = bufp-buffer;
  1453.             bcopy(buffer, tty_text, tty_textlen);
  1454.             return(ptr->value);
  1455.         }
  1456.         else
  1457.         {
  1458.             ptr = ptr->child;
  1459.             if (!alarmset) {
  1460.             alarmset = TRUE;
  1461.             oldsigalrm = signal(SIGALRM, sigalrm);
  1462.             }
  1463.             (void) ualarm(200000L);
  1464.         }
  1465.         }
  1466.         
  1467.     } while (ptr != NULL);
  1468.     
  1469.     if (alarmset) {
  1470.         (void) ualarm(0L);
  1471.         (void) signal(SIGALRM, oldsigalrm);
  1472.     }
  1473.     
  1474.     if (bufp <= buffer)
  1475.         return(EOF);
  1476.     while (--bufp > buffer)
  1477.         tty_backbuf[tty_backcnt++] = *bufp;
  1478.     return(*bufp);
  1479. }
  1480.  
  1481. static
  1482. sigalrm()
  1483. {
  1484.     longjmp(jmpbuf, 1);
  1485. }
  1486.  
  1487. /*
  1488.  * ualarm(usec).  If this doesn't compile, just use alarm(0) and alarm(1).
  1489.  */
  1490. #include <sys/time.h>
  1491.  
  1492. #define    MILLION    1000000L
  1493.  
  1494. ualarm(usecs)
  1495.     long usecs;
  1496. {
  1497.     struct itimerval it, oitv;
  1498.     register struct itimerval *itp = ⁢
  1499.  
  1500.     timerclear(&itp->it_interval);
  1501.     itp->it_value.tv_sec = usecs/MILLION;
  1502.     itp->it_value.tv_usec = usecs%MILLION;
  1503.     if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
  1504.         return (-1);
  1505.     return (oitv.it_value.tv_sec*MILLION+oitv.it_value.tv_usec);
  1506. }
  1507. #endif
  1508. SHAR_EOF
  1509. if test 6283 -ne "`wc -c < 'getch.c'`"
  1510. then
  1511.     echo shar: error transmitting "'getch.c'" '(should have been 6283 characters)'
  1512. fi
  1513. fi # end of overwriting check
  1514. echo shar: extracting "'hacks.c'" '(11742 characters)'
  1515. if test -f 'hacks.c'
  1516. then
  1517.     echo shar: will not over-write existing file "'hacks.c'"
  1518. else
  1519. sed 's/^X//' << \SHAR_EOF > 'hacks.c'
  1520. /*
  1521.  *************
  1522.  * DISTRIBUTION NOTICE  July 30 1985
  1523.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  1524.  *        Research Triangle Institute, (919) 541-7005.
  1525.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  1526.  *        Naval Research Laboratory, (202) 767-3365.
  1527.  * No claims or warranties of any sort are made for this distribution.
  1528.  * General permission is granted to copy, but not for profit,
  1529.  * any of this distribution, provided that this notice
  1530.  * is always included in the copies.
  1531.  *************
  1532.  */
  1533. /*
  1534.  * hacks.c
  1535.  * curses-package routines missing in one version or another,
  1536.  * or corrections for routines in one version or another,
  1537.  * or whatever.
  1538.  */
  1539. #include "wm.h"
  1540.  
  1541. /*
  1542.  * Special redefinitions.  We get right into the dirt here.
  1543.  */
  1544. #ifndef TERMINFO
  1545. #define    _line        _y
  1546. #define    chtype        char
  1547. #define    _firstchar    _firstch
  1548. #define    _lastchar    _lastch
  1549. #endif
  1550.  
  1551. /*
  1552.  * Move physical cursor to (y,x).
  1553.  * If y is past the end of the screen, scroll the screen up.
  1554.  * This is an ugly routine in either version of curses,
  1555.  * perhaps because no one worried about this sort of thing.
  1556.  * (It would be nice to be able to request 'anywhere on line y',
  1557.  * or 'anywhere in column x', since more optimizations are then possible.)
  1558.  */
  1559. movecursor(y,x)
  1560. register int y, x;
  1561. {
  1562.     if (cursrow() == y && curscol() == x)
  1563.     return(0);
  1564. #ifdef TERMINFO
  1565.     if (y >= LINES) {
  1566.     (void) movecursor(y-1,x);
  1567.     vidattr(A_NORMAL);
  1568.     putp(scroll_forward);
  1569.     return(1);
  1570.     }
  1571.     Untouchwin(stdscr);
  1572.     leaveok(stdscr, FALSE);
  1573.     wmove(stdscr, y, x);
  1574.     wrefresh(stdscr);
  1575.     leaveok(stdscr, TRUE);
  1576. #else
  1577.     /* Couldn't mvcur handle the move_standout_mode problem? */
  1578.     if ((curscr->_flags&_STANDOUT) && !move_standout_mode) {
  1579.     putp(exit_standout_mode);
  1580.     curscr->_flags &= ~_STANDOUT;
  1581.     }
  1582.     /* speed hack: short circuit mvcur for simple scrolling */
  1583.     if (y == LINES && curscol() == x && cursrow()+2 == y && cursor_down) {
  1584.     putp(cursor_down);
  1585.     putp(scroll_forward);
  1586.     }
  1587.     else
  1588.     mvcur(cursrow(), curscol(), y, x);
  1589.     /* Couldn't mvcur update curscr's current (y,x) coordinate? */
  1590.     if (y >= LINES)
  1591.     y = LINES-1;
  1592.     cursrow() = y; curscol() = x;
  1593. #endif
  1594.     return(1);
  1595. }
  1596.  
  1597. /*
  1598.  * Make it appear that every location on the window is unchanged.
  1599.  */
  1600. untouchwin(wp)
  1601. register WINDOW *wp;
  1602. {
  1603.     register int i;
  1604.  
  1605.     for (i=0; i<wlines(wp); i++) {
  1606.     wp->_firstchar[i] = _NOCHANGE;
  1607. #ifdef TERMINFO
  1608.     wp->_lastchar[i] = _NOCHANGE;
  1609.     wp->_numchngd[i] = 0;
  1610. #endif
  1611.     }
  1612. }
  1613.  
  1614. /*
  1615.  * This is a replacement overwrite() routine for both curses versions.
  1616.  * The termcap version is slow and has some minor bugs.
  1617.  * The terminfo version aligns the two windows at their origins,
  1618.  * rather than on the virtual screen, making it less useful
  1619.  * as one cannot use 'mvwin' &etc to paint one window at an
  1620.  * arbitrary place on another.
  1621.  * Neither version documents what is done with 'standout' information.
  1622.  * This version copies the standout information for each character
  1623.  * so that a truly identical copy is made, which is handy for painting.
  1624.  */
  1625. /*********************************************************************
  1626. *                         COPYRIGHT NOTICE                           *
  1627. **********************************************************************
  1628. *        This software is copyright (C) 1982 by Pavel Curtis         *
  1629. *                                                                    *
  1630. *        Permission is granted to reproduce and distribute           *
  1631. *        this file by any means so long as no fee is charged         *
  1632. *        above a nominal handling fee and so long as this            *
  1633. *        notice is always included in the copies.                    *
  1634. *                                                                    *
  1635. *        Other rights are reserved except as explicitly granted      *
  1636. *        by written permission of the author.                        *
  1637. *                Pavel Curtis                                        *
  1638. *                Computer Science Dept.                              *
  1639. *                405 Upson Hall                                      *
  1640. *                Cornell University                                  *
  1641. *                Ithaca, NY 14853                                    *
  1642. *                                                                    *
  1643. *                Ph- (607) 256-4934                                  *
  1644. *                                                                    *
  1645. *                Pavel.Cornell@Udel-Relay   (ARPAnet)                *
  1646. *                decvax!cornell!pavel       (UUCPnet)                *
  1647. *********************************************************************/
  1648.  
  1649. /*
  1650. **
  1651. **    overwrite(win1, win2)
  1652. **
  1653. **
  1654. **    overwrite() writes win1 on win2 destructively.
  1655. **
  1656. **/
  1657.  
  1658. overwrite(win1, win2)
  1659. WINDOW    *win1, *win2;
  1660. {
  1661.     register chtype    *w1ptr, *w2ptr;
  1662.     register int col, end_col;
  1663.     int line, offset_line, offset_col, start_line, start_col, end_line;
  1664.     short   *firstchar, *lastchar;
  1665.  
  1666. #ifdef TRACE
  1667.     if (_tracing)
  1668.         _tracef("overwrite(%o, %o) called", win1, win2);
  1669. #endif
  1670.     
  1671.     offset_line = wbegy(win1) - wbegy(win2);
  1672.     offset_col = wbegx(win1) - wbegx(win2);
  1673.     start_line = MAX(offset_line, 0);
  1674.     start_col = MAX(offset_col, 0);
  1675.     end_line = offset_line + wlines(win1) - wlines(win2);
  1676.     end_line = wlines(win2) + MIN(end_line, 0);
  1677.     end_col = offset_col + wcols(win1) - wcols(win2);
  1678.     end_col = wcols(win2) + MIN(end_col, 0);
  1679.     firstchar = &win2->_firstchar[start_line];
  1680.     lastchar = &win2->_lastchar[start_line];
  1681.  
  1682.     for(line = start_line;  line < end_line;  line++)
  1683.     {
  1684.         short   fc, lc;
  1685.         
  1686.         w1ptr = &win1->_line[line-offset_line][start_col-offset_col];
  1687.         w2ptr = &win2->_line[line][start_col];
  1688.         fc = lc = _NOCHANGE;
  1689.  
  1690.         for(col = start_col;  col < end_col;  col++)
  1691.         {
  1692.         if (*w1ptr != *w2ptr)
  1693.         {
  1694.             *w2ptr = *w1ptr;
  1695.             if (fc == _NOCHANGE)
  1696.             fc = col;
  1697.             lc = col;
  1698.         }
  1699.  
  1700.         w1ptr++;
  1701.         w2ptr++;
  1702.         }
  1703.  
  1704.         if (*firstchar == _NOCHANGE)
  1705.         {
  1706.         *firstchar = fc;
  1707.         *lastchar = lc;
  1708.         }
  1709.         else if (fc != _NOCHANGE)
  1710.         {
  1711.         if (fc < *firstchar)
  1712.             *firstchar = fc;
  1713.  
  1714.         if (lc > *lastchar)
  1715.             *lastchar = lc;
  1716.         }
  1717.         
  1718.         firstchar++;
  1719.         lastchar++;
  1720.     }
  1721. }
  1722.  
  1723. #ifndef TERMINFO
  1724. /*
  1725.  * Emulators for terminfo curses procedures.
  1726.  */
  1727.  
  1728. #ifdef SET_WINDOW
  1729. /*
  1730.  *    tparm.c (Copyright Pavel Curtis, copyright notice above applies)
  1731.  */
  1732. /*
  1733.  *    char *
  1734.  *    tparm(string, parms)
  1735.  *
  1736.  *    Substitute the given parameters into the given string.
  1737.  */
  1738.  
  1739. #define STACKSIZE    20
  1740.  
  1741. #define npush(x)    if (stack_ptr < STACKSIZE) {stack[stack_ptr].num = x;\
  1742.                                                 stack_ptr++;\
  1743.                                                }
  1744. #define npop()       (stack_ptr > 0  ?  stack[--stack_ptr].num  :  0)
  1745. #define spop()       (stack_ptr > 0  ?  stack[--stack_ptr].str  :  (char *) 0)
  1746.  
  1747. typedef union
  1748. {
  1749.     unsigned int    num;
  1750.     char        *str;
  1751. }        stack_frame;
  1752.  
  1753. stack_frame    stack[STACKSIZE];
  1754. static    int    stack_ptr;
  1755. static    char    buffer[256];
  1756. static    int    *param;
  1757. static    char    *bufptr;
  1758. static    int    variable[26];
  1759.  
  1760. /*VARARGS1*/
  1761. char *
  1762. tparm(string, parms)
  1763. char    *string;
  1764. int    parms;
  1765. {
  1766.     char    len;
  1767.     int    number;
  1768.     int    level;
  1769.     int    x, y;
  1770.  
  1771.     param = &parms;
  1772.  
  1773.     stack_ptr = 0;
  1774.     bufptr = buffer;
  1775.  
  1776.     while (*string)
  1777.     {
  1778.         if (*string != '%')
  1779.         *(bufptr++) = *string;
  1780.         else
  1781.         {
  1782.         string++;
  1783.         switch (*string)
  1784.         {
  1785.             default:
  1786.             break;
  1787.  
  1788.             case '%':
  1789.             *(bufptr++) = '%';
  1790.             break;
  1791.  
  1792.             case 'd':
  1793.             (void) sprintf(bufptr, "%d", npop());
  1794.             bufptr += strlen(bufptr);
  1795.             break;
  1796.  
  1797.             case '0':
  1798.             string++;
  1799.             len = *string;
  1800.             if ((len == '2'  ||  len == '3')  &&  *++string == 'd')
  1801.             {
  1802.                 if (len == '2')
  1803.                 (void) sprintf(bufptr, "%02d", npop());
  1804.                 else
  1805.                 (void) sprintf(bufptr, "%03d", npop());
  1806.                 
  1807.                 bufptr += strlen(bufptr);
  1808.             }
  1809.             break;
  1810.  
  1811.             case '2':
  1812.             string++;
  1813.             if (*string == 'd')
  1814.             {
  1815.                 (void) sprintf(bufptr, "%2d", npop());
  1816.                 bufptr += strlen(bufptr);
  1817.             }
  1818.             break;
  1819.  
  1820.             case '3':
  1821.             string++;
  1822.             if (*string == 'd')
  1823.             {
  1824.                 (void) sprintf(bufptr, "%3d", npop());
  1825.                 bufptr += strlen(bufptr);
  1826.             }
  1827.             break;
  1828.  
  1829.             case 'c':
  1830.             *(bufptr++) = (char) npop();
  1831.             break;
  1832.  
  1833.             case 's':
  1834.             strcpy(bufptr, spop());
  1835.             bufptr += strlen(bufptr);
  1836.             break;
  1837.  
  1838.             case 'p':
  1839.             string++;
  1840.             if (*string >= '1'  &&  *string <= '9')
  1841.                 npush(param[*string - '1']);
  1842.             break;
  1843.  
  1844.             case 'P':
  1845.             string++;
  1846.             if (*string >= 'a'  &&  *string <= 'z')
  1847.                 variable[*string - 'a'] = npop();
  1848.             break;
  1849.  
  1850.             case 'g':
  1851.             string++;
  1852.             if (*string >= 'a'  &&  *string <= 'z')
  1853.                 npush(variable[*string - 'a']);
  1854.             break;
  1855.  
  1856.             case '\'':
  1857.             string++;
  1858.             npush(*string);
  1859.             string++;
  1860.             break;
  1861.  
  1862.             case '{':
  1863.             number = 0;
  1864.             string++;
  1865.             while (*string >= '0'  &&  *string <= '9')
  1866.             {
  1867.                 number = number * 10 + *string - '0';
  1868.                 string++;
  1869.             }
  1870.             npush(number);
  1871.             break;
  1872.  
  1873.             case '+':
  1874.             y = npop();
  1875.             x = npop();
  1876.             npush(x + y);
  1877.             break;
  1878.  
  1879.             case '-':
  1880.             y = npop();
  1881.             x = npop();
  1882.             npush(x - y);
  1883.             break;
  1884.  
  1885.             case '*':
  1886.             y = npop();
  1887.             x = npop();
  1888.             npush(x * y);
  1889.             break;
  1890.  
  1891.             case '/':
  1892.             y = npop();
  1893.             x = npop();
  1894.             npush(x / y);
  1895.             break;
  1896.  
  1897.             case 'm':
  1898.             y = npop();
  1899.             x = npop();
  1900.             npush(x % y);
  1901.             break;
  1902.  
  1903.             case '&':
  1904.             y = npop();
  1905.             x = npop();
  1906.             npush(x & y);
  1907.             break;
  1908.  
  1909.             case '|':
  1910.             y = npop();
  1911.             x = npop();
  1912.             npush(x | y);
  1913.             break;
  1914.  
  1915.             case '^':
  1916.             y = npop();
  1917.             x = npop();
  1918.             npush(x ^ y);
  1919.             break;
  1920.  
  1921.             case '=':
  1922.             y = npop();
  1923.             x = npop();
  1924.             npush(x == y);
  1925.             break;
  1926.  
  1927.             case '<':
  1928.             y = npop();
  1929.             x = npop();
  1930.             npush(x < y);
  1931.             break;
  1932.  
  1933.             case '>':
  1934.             y = npop();
  1935.             x = npop();
  1936.             npush(x > y);
  1937.             break;
  1938.  
  1939.             case '!':
  1940.             x = npop();
  1941.             npush(! x);
  1942.             break;
  1943.  
  1944.             case '~':
  1945.             x = npop();
  1946.             npush(~ x);
  1947.             break;
  1948.  
  1949.             case 'i':
  1950.             param[0]++;
  1951.             param[1]++;
  1952.             break;
  1953.  
  1954.             case '?':
  1955.             break;
  1956.  
  1957.             case 't':
  1958.             x = npop();
  1959.             if (x)
  1960.             {
  1961.                 /* do nothing; keep executing */
  1962.             }
  1963.             else
  1964.             {
  1965.                 /* scan forward for %e or %; at level zero */
  1966.                 string++;
  1967.                 level = 0;
  1968.                 while (*string)
  1969.                 {
  1970.                     if (*string == '%')
  1971.                     {
  1972.                     string++;
  1973.                     if (*string == '?')
  1974.                         level++;
  1975.                     else if (*string == ';')
  1976.                     {
  1977.                         if (level > 0)
  1978.                         level--;
  1979.                         else
  1980.                         break;
  1981.                     }
  1982.                     else if (*string == 'e'  && level == 0)
  1983.                         break;
  1984.                     }
  1985.  
  1986.                     if (*string)
  1987.                     string++;
  1988.                 }
  1989.             }
  1990.             break;
  1991.  
  1992.             case 'e':
  1993.             /* scan forward for a %; at level zero */
  1994.                 string++;
  1995.                 level = 0;
  1996.                 while (*string)
  1997.                 {
  1998.                 if (*string == '%')
  1999.                 {
  2000.                     string++;
  2001.                     if (*string == '?')
  2002.                     level++;
  2003.                     else if (*string == ';')
  2004.                     {
  2005.                     if (level > 0)
  2006.                         level--;
  2007.                     else
  2008.                         break;
  2009.                     }
  2010.                 }
  2011.  
  2012.                 if (*string)
  2013.                     string++;
  2014.                 }
  2015.             break;
  2016.  
  2017.             case ';':
  2018.             break;
  2019.  
  2020.         } /* endswitch (*string) */
  2021.         } /* endelse (*string == '%') */
  2022.  
  2023.         if (*string == '\0')
  2024.         break;
  2025.         
  2026.         string++;
  2027.     } /* endwhile (*string) */
  2028.  
  2029.     *bufptr = '\0';
  2030.     return(buffer);
  2031. }
  2032. #endif
  2033.  
  2034. /*
  2035.  * Ring Bell.
  2036.  */
  2037. beep()
  2038. {
  2039.     putchar('\007');
  2040. }
  2041.  
  2042. /*
  2043.  * 'Ring' visual bell if available, otherwise audible bell.
  2044.  */
  2045. flash()
  2046. {
  2047.     /* If you get a syntax error on this routine,
  2048.      * you are not using the new curses.h!  Put
  2049.      * it in this directory or in /usr/include (saving the old one).
  2050.      * And double check that you are linking with the new libcurses.a
  2051.      */
  2052.     if (flash_screen)
  2053.     putp(flash_screen);
  2054.     else
  2055.     beep();
  2056. }
  2057.  
  2058. /*
  2059.  * Return the baud rate of the current terminal.
  2060.  */
  2061. baudrate()
  2062. {
  2063. #ifdef    B9600
  2064.     if (_tty.sg_ospeed >= B9600)
  2065.     return(9600);
  2066. #endif
  2067. #ifdef    B4800
  2068.     if (_tty.sg_ospeed >= B4800)
  2069.     return(4800);
  2070. #endif
  2071.     return(1200);
  2072. }
  2073.  
  2074. erasechar() { return(_tty.sg_erase); }
  2075. killchar() { return(_tty.sg_kill); }
  2076. #endif
  2077. SHAR_EOF
  2078. if test 11742 -ne "`wc -c < 'hacks.c'`"
  2079. then
  2080.     echo shar: error transmitting "'hacks.c'" '(should have been 11742 characters)'
  2081. fi
  2082. fi # end of overwriting check
  2083. echo shar: extracting "'help.c'" '(2137 characters)'
  2084. if test -f 'help.c'
  2085. then
  2086.     echo shar: will not over-write existing file "'help.c'"
  2087. else
  2088. sed 's/^X//' << \SHAR_EOF > 'help.c'
  2089. /*
  2090.  *************
  2091.  * DISTRIBUTION NOTICE  July 30 1985
  2092.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  2093.  *        Research Triangle Institute, (919) 541-7005.
  2094.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  2095.  *        Naval Research Laboratory, (202) 767-3365.
  2096.  * No claims or warranties of any sort are made for this distribution.
  2097.  * General permission is granted to copy, but not for profit,
  2098.  * any of this distribution, provided that this notice
  2099.  * is always included in the copies.
  2100.  *************
  2101.  */
  2102. #include "wm.h"
  2103.  
  2104.  
  2105. /*
  2106.  * print a command summary over the top of the screen, then redraw
  2107.  */
  2108. helpmsg()
  2109. {
  2110. printf("Code    Command  Description\r\n");
  2111. printf("----    -------  -----------\r\n");
  2112. printf("%d..%d    change    Change to the named window\r\n",
  2113.     MINWINDOW, MAXWINDOWS-1);
  2114. printf("d       dump      dump current window contents to a file\r\n");
  2115. printf("h or ?  help      print this help message\r\n");
  2116. printf("i       identify  identify windows\r\n");
  2117. printf("k       kill      kill a window permanently\r\n");
  2118. printf("l       last      change to last-used window\r\n");
  2119. printf("m       move      move and/or change size of current window\r\n");
  2120. printf("n       new       make a new window\r\n");
  2121. printf("p       prefix    change WM prefix character (See EXECUTE below)\r\n");
  2122. printf("q       quit      quit WM\r\n");
  2123. printf("r       redraw    redraw entire screen\r\n");
  2124. printf("s       save      save current window configuration\r\n");
  2125. printf("t       termcap   reset $TERM and $TERMCAP of current window\r\n");
  2126. printf("z       suspend   suspend WM (or spawn non-window subshell)\r\n");
  2127.  
  2128. printf("----------------------------------------------------------\r\n");
  2129.  
  2130. printf("To EXECUTE a command, type the WM prefix character (%s) then the command code.\r\n", mkprint(prefix));
  2131. printf("To ENTER the prefix character itself, type it twice.\r\n");
  2132. printf("To CANCEL a WM command before it executes, type <ESC> or <DEL>.\r\n");
  2133. printf("For FUTHER INFORMATION, consult the 'wm' manual entry.\r\n");
  2134.  
  2135. printf("------------------------------\r\n");
  2136.  
  2137. printf("Now hit any key to return to WM");
  2138. (void)fflush(stdout);
  2139. }
  2140. SHAR_EOF
  2141. if test 2137 -ne "`wc -c < 'help.c'`"
  2142. then
  2143.     echo shar: error transmitting "'help.c'" '(should have been 2137 characters)'
  2144. fi
  2145. fi # end of overwriting check
  2146. #    End of shell archive
  2147. exit 0
  2148.